home *** CD-ROM | disk | FTP | other *** search
- //* Table.Cpp
- //*
- //* Functions to Handle File Input, Indexing and Searching Methods for
- //* use with Ascii Non-delimited Files... ( or delimited files )
- //*
- //***************************************************************************
-
- #include <io.h>
- #include <fcntl.h>
- #include <sys\stat.h>
- #include <string.h>
- #include "table.h"
-
- int Table::usage=0;
- IndexTable* Table::pIndex[10];
- Table* Table::pTable[10];
-
-
- //**************************************************************************
- Table::Table(char *file, Record *record)
- {
- if (!usage)
- for (int i=0; i<10; i++)
- {
- pIndex[i] = NULL;
- pTable[i] = NULL;
- }
-
- pRecord = record;
- cursor = 0;
- fileSize = 0;
- recCount = 0;
- recLength = pRecord->Length();
-
- hFile = _open(file,O_RDONLY|O_BINARY);
- if (hFile>0)
- {
- fileSize = filelength(hFile);
- recCount = fileSize/recLength;
- }
- usage++;
- }
-
-
- //**************************************************************************
- Table::~Table(void)
- {
- usage--;
- if (hFile>0)
- _close(hFile);
-
- for (int i=0; i<10; i++)
- {
- if (pTable[i]==this && pIndex[i])
- {
- delete pIndex[i];
- unlink(indexName(i));
- }
- }
- }
-
-
- //**************************************************************************
- int Table::Get(void)
- {
- if (recCount<1)
- return(TBL_EMPTY);
-
- lseek(hFile,cursor*recLength,SEEK_SET);
- _read(hFile,pRecord->Buffer,recLength);
- return(TBL_OK);
- }
-
-
- //**************************************************************************
- int Table::gotoFirst(int ihandle)
- {
- if (recCount<1)
- return(TBL_EMPTY);
-
- cursor = ihandle == -1 ? 0 : pIndex[ihandle]->getFirst();
- return(TBL_OK);
- }
-
- //**************************************************************************
- int Table::gotoLast(int ihandle)
- {
- if (recCount<1)
- return(TBL_EMPTY);
-
- cursor = ihandle==-1 ? recCount-1 : pIndex[ihandle]->getLast();
- return(TBL_OK);
- }
-
-
- //**************************************************************************
- int Table::gotoNext(int ihandle)
- {
- if (recCount<1)
- return(TBL_EMPTY);
-
- if (ihandle == -1)
- {
- if (cursor+1==recCount)
- return(TBL_END);
- cursor++;
- }
- else
- {
- long next = pIndex[ihandle]->getNext();
- if (next==-1)
- return(TBL_END);
- cursor=next;
- }
- return(TBL_OK);
- }
-
-
- //**************************************************************************
- int Table::gotoPrev(int ihandle)
- {
- if (recCount<1)
- return(TBL_EMPTY);
-
- if (ihandle == -1)
- {
- if (cursor==0)
- return(TBL_BEGIN);
- cursor--;
- }
- else
- {
- long prev = pIndex[ihandle]->getPrev();
- if (prev==-1)
- return(TBL_END);
- cursor=prev;
- }
-
- return(TBL_OK);
- }
-
-
- //**************************************************************************
- int Table::gotoRecNum(long recnum)
- {
- if (recCount<1)
- return(TBL_EMPTY);
-
- if (recnum>=recCount)
- return(TBL_RANGE);
-
- cursor=recnum;
- return(TBL_OK);
- }
-
- //**************************************************************************
-
- int Table::Search(char *fldName, char *search)
- {
- return Search(pRecord->getFieldNum(fldName),search);
- }
-
-
- //**************************************************************************
- int Table::Search(int fldNum, char *search)
- {
- if (fldNum>=getRecCount() || fldNum<0)
- return TBL_RANGE;
-
- int stat;
- long i;
- char *fld = new char[pRecord->getFieldWidth(fldNum)+1];
-
- for (i=0,stat=gotoFirst(); stat==TBL_OK; stat=gotoNext())
- {
- Get();
- pRecord->getField(fldNum,fld);
- if (!strcmp(fld,search))
- {
- cursor=i;
- delete fld;
- return(TBL_OK);
- }
- }
- delete fld;
- gotoRecNum(cursor);
- Get();
- return(TBL_NOTFOUND);
- }
-
-
- //**************************************************************************
- int Table::Search(char *key, int ihandle)
- {
- long found = pIndex[ihandle]->findKey(key);
- if (found<0)
- return(TBL_NOTFOUND);
- cursor=found;
- return(TBL_OK);
- }
-
- //**************************************************************************
- int Table::openIndex(int *fields, int fcount)
- {
- // Find an empty slot for a new index
- for (int ix = 0 ; ix<10; ix++)
- if (!pIndex[ix])
- break;
-
- // No handles available return -1 (invalid handle)
- if (ix>=10)
- return(-1);
-
- pTable[ix]=this;
-
- keySize = 0;
- for (int i=0; i<fcount; i++)
- keySize += pRecord->getFieldWidth(fields[i]);
-
- IndexTable *index=new IndexTable(indexName(ix),keySize);
-
- char *key = new char[keySize+1];
-
- for (int stat=gotoFirst(); stat==TBL_OK; stat=gotoNext())
- {
- Get();
- int n=0;
- for (int f=0; f<fcount; f++,n+=pRecord->getFieldWidth(fields[f]))
- pRecord->getField(fields[f],key+n);
- index->addKey(key,cursor);
- }
- pIndex[ix]=index;
- return(ix);
- }
-
-
- //**************************************************************************
- int Table::closeIndex(int ix)
- {
- if (pIndex[ix] && pTable[ix]==this)
- {
- delete pIndex[ix];
- pIndex[ix] = NULL;
- pTable[ix] = NULL;
- return(1);
- }
- return(0);
- }
-
-
- //**************************************************************************
- char* Table::indexName(int handle)
- {
- static char name[13];
- strcpy(name,"table.ix");
- name[8]=handle+'0';
- name[9]=0;
- return(name);
- }
-
-
- //**************************************************************************
- IndexTable::IndexTable(char *name, int keysize)
- {
- unlink(name);
- handle = open(name,O_RDWR|O_BINARY|O_CREAT,S_IREAD|S_IWRITE);
- keySize = keysize;
- keyCount = 0;
- Key = new char[keySize];
- }
-
-
- //**************************************************************************
- IndexTable::~IndexTable(void)
- {
- delete Key;
- close(handle);
- }
-
-
- //**************************************************************************
- void IndexTable::addKey(char *key, long recnum)
- {
- char loc;
-
- if (keyCount>0)
- {
- lseek(handle,current=0l,SEEK_SET);
- while(1)
- {
- read(handle,Key,keySize);
- read(handle,&keyData,sizeof(KeyData));
-
- if (memcmp(key,Key,keySize)<=0)
- {
- if (keyData.left == -1)
- {
- keyData.left=keyCount*(keySize+sizeof(KeyData));
- loc = 'L';
- break;
- }
- else
- current = lseek(handle,keyData.left,SEEK_SET);
- }
- else
- {
- if (keyData.right == -1)
- {
- keyData.right=keyCount*(keySize+sizeof(KeyData));
- loc = 'R';
- break;
- }
- else
- current = lseek(handle,keyData.right,SEEK_SET);
- }
- }
- lseek(handle,current+keySize,SEEK_SET);
- write(handle,&keyData,sizeof(KeyData));
- }
- else {
- loc=0;
- current=-1;
- }
-
- keyData.recnum = recnum;
- keyData.parent = current;
- keyData.loc = loc;
- keyData.left = -1;
- keyData.right = -1;
-
- current=lseek(handle,0l,SEEK_END);
- write(handle,key,keySize);
- write(handle,&keyData,sizeof(KeyData));
-
- keyCount++;
- }
-
-
- //**************************************************************************
- long IndexTable::getFirst(long start)
- {
- keyData.left = start;
- while(keyData.left != -1)
- {
- current= keyData.left;
- lseek(handle,keyData.left+keySize,SEEK_SET);
- read(handle,&keyData,sizeof(KeyData));
- }
- return(keyData.recnum);
- }
-
- //**************************************************************************
- long IndexTable::getLast(long start)
- {
- keyData.right = start;
- while(keyData.right != -1)
- {
- current=keyData.right;
- lseek(handle,keyData.right+keySize,SEEK_SET);
- read(handle,&keyData,sizeof(KeyData));
- }
- return(keyData.recnum);
- }
-
- //**************************************************************************
- long IndexTable::getNext(void)
- {
- char prevloc=0;
-
- while(1) {
-
- if (current==-1)
- return(-1);
-
- lseek(handle,current+keySize,SEEK_SET);
- read(handle,&keyData,sizeof(KeyData));
-
- if (prevloc == 'L')
- return(keyData.recnum);
-
- if (prevloc != 'R' && keyData.right>= 0)
- return(getFirst(keyData.right));
-
- prevloc = keyData.loc;
- current=keyData.parent;
-
- if (current==-1)
- return(-1);
-
- lseek(handle,keyData.parent+keySize,SEEK_SET);
- read(handle,&keyData,sizeof(KeyData));
-
- if (prevloc=='L')
- return(keyData.recnum);
-
- prevloc = keyData.loc;
- current=keyData.parent;
- }
- }
-
- //**************************************************************************
- long IndexTable::getPrev(void)
- {
- char prevloc=0;
-
- while(1) {
-
- if (current==-1)
- return(-1);
-
- lseek(handle,current+keySize,SEEK_SET);
- read(handle,&keyData,sizeof(KeyData));
-
- if (prevloc == 'R')
- return(keyData.recnum);
-
- if (prevloc != 'L' && keyData.left>= 0)
- return(getLast(keyData.left));
-
- prevloc = keyData.loc;
- current=keyData.parent;
-
- if (current==-1)
- return(-1);
-
- lseek(handle,keyData.parent+keySize,SEEK_SET);
- read(handle,&keyData,sizeof(KeyData));
-
- if (prevloc=='R')
- return(keyData.recnum);
-
- prevloc = keyData.loc;
- current=keyData.parent;
- }
- }
-
- //**************************************************************************
- long IndexTable::findKey(char *key)
- {
- long location;
-
- lseek(handle,location=0l,SEEK_SET);
- while(1) {
- read(handle,Key,keySize);
- read(handle,&keyData,sizeof(KeyData));
-
- if (memcmp(key,Key,keySize)==0)
- {
- current=location;
- return(keyData.recnum);
- }
-
- if (memcmp(key,Key,keySize)<0)
- {
- if (keyData.left == -1)
- return(-1);
- location = lseek(handle,keyData.left,SEEK_SET);
- }
- else
- {
- if (keyData.right == -1)
- return(-1);
- location = lseek(handle,keyData.right,SEEK_SET);
- }
- }
- }
-